#-------------------------------------------------------------------------------
# Student Name: Brandon Hawkins / Assignment: PA #4 / Date: 10/14/2011
#-------------------------------------------------------------------------------
# Honor Code Statement: I received no assistance on this assignment that
# violates the ethical guidelines set forth by professor and class syllabus.
#-------------------------------------------------------------------------------
# References: (list of web sites, texts, and any other resources used)
#-------------------------------------------------------------------------------
# Comments: (a note to the grader as to any problems or uncompleted aspects of
# of the assignment)
#-------------------------------------------------------------------------------
# Pseudocode:
# 
# open an existing .txt file or create a new one
#    get name of existing file or name of new file
#    if existing file:
#        show directory
#        get fileName from user
#        check file exists
#        readFile()
#    if new file:
#        get fileName from user
#        editFile()
#
# readFile():
#    open the file
#    use 1 loop to read lines into array and store each line in 2 dim array
#    remove extraneous punctuation/words
#    keep both 2 dim array and 1 dim array for ease later
#    mainMenu()
#
# editFile():
#    open file
#    write to file until user enters "EOF"
#    readFile()
#
# mainMenu():
#    (for all choices):
#        if choice is valid:
#            call appropriate function()
#
# ...various functions that strip/parse per requirements#
#
#-------------------------------------------------------------------------------
# Assumptions: third_words will exclude blank lines
#-------------------------------------------------------------------------------
# NOTE: width of source code should be <= 80 characters to facilitate printing
#-------------------------------------------------------------------------------

import sys
import os

# Global lists for choice validation.
a1 = {"One", "one", "1", 1}
a2 = {"Two", "two", "2", 2}
a3 = {"Three", "three", "3", 3}
a4 = {"Four", "four", "4", 4}
a5 = {"Five", "five", "5", 5}
a6 = {"Six", "six", "6", 6}
a7 = {"Seven", "seven", "7", 7}
a8 = {"Eight", "eight", "8", 8}
a9 = {"Nine", "nine", "9", 9}
allOptions = [a1, a2, a3, a4, a5, a6, a7, a8]
# Characters to strip per requirements
strips = ["\"", "\'", ".", ",", ":", ";", "/", "?", "!"]

def start_menu():
    """This is the initial menu presented to the user. Selects an existing file
        or creates a new file"""
    choice = raw_input("Menu\n\n1) Parse an existing .txt file\n" + 
                       "2) Create a new .txt file\n3) Exit\n\nPlease make a" + 
                       " selection: ")
    if choice in a1:
        print_dir()
        fileName = str(raw_input("\nEnter the file path (.txt): "))
        try:
            os.path.exists(fileName)
        except:
            print "That is not a valid entry."
            start_menu()  
        read_all_input(fileName)      
    if (choice in a2):
        fileName = str(raw_input("Enter a name for the .txt file being " + 
                                 "created.\nPlease include the file " + 
                                 "extension (.txt): "))
        edit_file(fileName)
    if choice in a3:
        sys.exit()
    else:
        print "Please enter a valid selection"
        start_menu()
        
def edit_file(fileName):
    """Opens passed file and allows user to add more text and appends each line
       to an array. Presents menu afterwards.
    """
    print ("Please enter text to write to file.\nWhen finished, enter a " + 
           "line with the text \"EOF\" (no quotes): ")
    text = ""
    f = open(fileName, "w+")
    while (text != "EOF"):
        text = str(raw_input())
        f.write(text + "\n")
    f.close()
    read_all_input(fileName)

def read_all_input(fileName):
    """Reads from the provided file and appends each line to an array.
       Presents menu afterwards.
    """
    oneDimArray = []
    twoDimArray = []
    f = open(fileName, "r+")
    readArray = f.readlines()
    # Split array of text read from file and append to new array 'oneDimArray'.
    for i in range (len(readArray)):
        oneDimArray.append(" ".join(readArray[i].split()))
        # Store each sentence in a list, then store the list in a new list.
        twoDimArray.append(oneDimArray[i].split())  
    f.close()
    # Remove "EOF".
    twoDimArray.pop()  
    # Strip punctuation and format per requirements.
    twoDimArray = strip_punctuation(twoDimArray) 
    # Convert stripped two dimensional array to one dim.
    oneDimArray = two_to_one(twoDimArray) 
    get_menu_choice(oneDimArray, twoDimArray) 
    
def two_to_one(twoDimArray):
    """Converts the passed 2-dimensional array and returns a
       1-dimensional array
       """
    try:
        oneDimArray = []
        for i in range(len(twoDimArray)):            
            for j in range(len(twoDimArray[i])):            
                oneDimArray.append(twoDimArray[i][j])        
        return oneDimArray
    except:
        print "Passed array is not a 2-dimensional array"
        return twoDimArray

def strip_punctuation(oneDimArray):
    """Strips punctuation (stored in strips[]), converts all chars to
       lowercase, and replaces blank lines with "." per requirements.
    """
    global strips        
    for i in range(len(oneDimArray)):            
        for j in range(len(oneDimArray[i])):
            oneDimArray[i][j] = oneDimArray[i][j].lower()
            if not oneDimArray[i][j]:
                oneDimArray[i].pop(j) 
            for k in range(len(strips)):
                oneDimArray[i] = [word.replace(strips[k], '') for word in
                                 oneDimArray[i]]
        if not oneDimArray[i]:
            oneDimArray[i] = ["."]          
    return oneDimArray   
    
def get_menu_choice(oneDimArray=None, twoDimArray=None):
    """Presents a menu of text parsing options"""
    global a1, a2, a3, a4, a5, a6, a7, allOptions 
    choice = raw_input("\n----------------------------\n1) Longest word\n2) " + 
                       "Shortest word\n3) Most common word\n4) First letter " + 
                       "of each word\n5) Last word of each line\n6) Total " + 
                       "word count\n7) Every third word\n8) Print in full" + 
                       "\n9) Exit\n----------------------------\n\nPlease " + 
                       "make a selection:")
    if choice in a9:
        sys.exit()
    elif (i for i, choice in allOptions):
        if choice in a1:
            print "Longest word: " + longest_word(oneDimArray)  
        elif choice in a2:
            print "Shortest word: " + shortest_word(oneDimArray)
        elif choice in a3:
            print ("Most common word (word, frequency): " + 
                   most_popular_word(oneDimArray))
        elif choice in a4:
            print "First letter of every word: " + first_letters(twoDimArray)
        elif choice in a5:
            print "Last word of each line: " + last_words(twoDimArray)
        elif choice in a6:
            print "Total word count: " + word_count(oneDimArray)
        elif choice in a7:
            print "Every third word: " + third_words(oneDimArray)
        elif choice in a8:
            print "Current text (full): " + str(twoDimArray)
        get_menu_choice(oneDimArray, twoDimArray)
    else:
        print "Please enter a valid selection"
        get_menu_choice(oneDimArray, twoDimArray) 
        
def print_dir():
    """Presents the current directory in a readable format"""
    print ("Current directory:\n")
    for dirname, dirnames, filenames in os.walk('.'):
        for subdirname in dirnames:
            print "\t" + os.path.join(dirname, subdirname)
        for filename in filenames:
            print "\t" + os.path.join(dirname, filename) 

def longest_word(oneDimArray):
    """Returns the longest word in the passed array"""
    # Exclude blank lines
    oneDimArray = [word for word in oneDimArray if word != '.']
    return ''.join(str(max(oneDimArray, key=len)))     
        
def shortest_word(oneDimArray):
    """Returns the shortest word in the passed array"""
    # Exclude blank lines
    oneDimArray = [word for word in oneDimArray if word != '.']
    return ''.join(str(min(oneDimArray, key=len)))

def most_popular_word(oneDimArray):
    """Returns the most common word in the passed array"""
    # Exclude blank lines
    oneDimArray = [word for word in oneDimArray if word != '.']
    words = {}
    for word in oneDimArray:
        words[word] = words.get(word, 0) + 1
    oneDimArray = sorted(words.iteritems(),
                   key=lambda(word, count): (-count, word))[:1]
    return str([word for word in oneDimArray][0])

def first_letters(twoDimArray):
    """Returns the first letter of each word/line in the passed array"""
    result = ""
    for i in range (len(twoDimArray)):
        # Don't append blank space to first
        if (i != 0):
            result += " "
        for j in range (len(twoDimArray[i])):
            result += str(twoDimArray[i][j][0])
    return str(result)   

def last_words(twoDimArray):
    """Returns the last word of each line in the passed array"""
    result = ""
    for i in range(len(twoDimArray)):
        # Exclude blank lines
        if twoDimArray[i][(len(twoDimArray[i]) - 1)] != '.':
            # Don't append blank space to first
            if (i != 0):
                result += " "
            result += str(twoDimArray[i][(len(twoDimArray[i]) - 1)])
    return str(result)

def word_count(oneDimArray):
    """Returns the number of words in the passed array"""
    return str(len(oneDimArray))

def third_words(oneDimArray):
    """Returns every third word in the passed array"""
    # Exclude blank lines
    oneDimArray = [word for word in oneDimArray if word != '.']
    result = ""
    for i in range (len(oneDimArray)):
        if (i % 3 == 0):
            if (i != 0):
                result += " "
            result += str(oneDimArray[i])
    return str(result)

# Run script    
start_menu()
